home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / ck5a189s / ckuscr.c < prev    next >
C/C++ Source or Header  |  1993-06-26  |  12KB  |  413 lines

  1. #ifndef NOICP
  2. #ifndef NOSCRIPT
  3. char *loginv = "Script Command, 5A(016) 26 Jun 93";
  4.  
  5. /*  C K U S C R  --  Login script for logging onto remote system */
  6.  
  7. /*
  8.   Copyright (C) 1985, 1993, Trustees of Columbia University in the City of New
  9.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  10.   sold for profit as a software product itself, nor may it be included in or
  11.   distributed with commercial products or otherwise distributed by commercial
  12.   concerns to their clients or customers without written permission of the
  13.   Office of Kermit Development and Distribution, Columbia University.  This
  14.   copyright notice must not be removed, altered, or obscured.
  15.  
  16.   Original (version 1, 1985) author: Herm Fischer, Encino, CA.
  17.   Contributed to Columbia University in 1985 for inclusion in C-Kermit 4.0.
  18.   Author and maintainer since 1985: Frank da Cruz, Columbia University,
  19.   fdc@columbia.edu.
  20. */
  21.  
  22. /*
  23.   The module expects a login string of the expect send [expect send] ...
  24.   format.  It is intended to operate similarly to the way the common
  25.   uucp "L.sys" login entries work.  Conditional responses are supported
  26.   expect[-send-expect[...]] as with uucp.  The send keyword EOT sends a
  27.   control-d, and the keyword BREAK sends a break.  Letters prefixed
  28.   by '~' are '~b' backspace, '~s' space, '~n' linefeed, '~r' return, '~x' xon,
  29.   '~t' tab, '~q' ? (not allowed on kermit command lines), '~' ~, '~'',
  30.   '~"', '~c' don't append return, '~o[o[o]]' octal character.  As with
  31.   some uucp systems, sent strings are followed by ~r (not ~n) unless they
  32.   end with ~c. Null expect strings (e.g., ~0 or --) cause a short
  33.   delay, and are useful for sending sequences requiring slight pauses.
  34.  
  35.   This module calls externally defined system-dependent functions for
  36.   communications i/o, as defined in CKCPLM.DOC, the C-Kermit Program Logic
  37.   Manual, and thus should be portable to all systems that implement those
  38.   functions, and where alarm() and signal() work as they do in UNIX.
  39. */
  40.  
  41. #include "ckcdeb.h"
  42. #include <signal.h>
  43. #include <setjmp.h>
  44. #include "ckcasc.h"
  45. #include "ckcker.h"
  46. #include "ckuusr.h"
  47. #include "ckcnet.h"
  48.  
  49. _PROTOTYP( VOID flushi, (void) );
  50.  
  51. #ifdef MAC
  52. #define SIGALRM (1<<10)
  53. #undef SIGTYP                /* put in ckcdeb.h later */
  54. #define SIGTYP void
  55. #endif /* MAC */
  56.  
  57. extern int local, flow, seslog, mdmtyp, msgflg, duplex, backgrd, secho, quiet;
  58. #ifdef NETCONN
  59. extern int network, ttnproto;
  60. #endif /* NETCONN */
  61. extern long speed;
  62. extern char ttname[];
  63.  
  64. #ifndef NOSPL
  65. extern struct cmdptr cmdstk[];
  66. extern int techo, cmdlvl;
  67. extern int mecho;
  68. #endif /* NOSPL */
  69.  
  70. static int scr_echo;            /* Whether to echo script commands */
  71.  
  72. static int exp_alrm = 15;        /* Time to wait for expect string */
  73. #define SND_ALRM 15            /* Time to allow for sending string */
  74. #define NULL_EXP 2            /* Time to pause on null expect strg*/ 
  75. #define DEL_MSEC 300            /* milliseconds to pause on ~d */
  76.  
  77. #define SBUFL 512        
  78. static char seq_buf[SBUFL], *s;        /* Login Sequence buffer */
  79. static char fls_buf[SBUFL];        /* Flush buffer */
  80. static int got_it, no_cr;
  81.  
  82. /*  connect state parent/child communication signal handlers */
  83.  
  84. static jmp_buf alrmrng;            /* Envir ptr for connect errors */
  85.  
  86. SIGTYP
  87. scrtime(foo) int foo; {            /* modem read failure handler, */
  88.     longjmp(alrmrng,1);            /* notifies parent process to stop */
  89. }
  90.  
  91. /*
  92.  Sequence interpreter -- pick up next sequence from command string,
  93.  decode escapes and place into seq_buf.
  94.  
  95.  If string contains a ~d (delay) then sequenc returns a 1 expecting
  96.  to be called again after the ~d executes.
  97. */
  98. static int
  99. sequenc() {
  100.     int i;
  101.     char c, oct_char;
  102.  
  103.     no_cr = 0;                /* output needs cr appended */
  104.     for (i = 0; i < SBUFL; ) {        
  105.     if (*s == '\0' || *s == '-' || isspace(*s) ) { /* done */
  106.         seq_buf[i] = '\0';
  107.         return(0) ;
  108.     }
  109.     if (*s == '~') {        /* escape character */
  110.         s++;
  111.         switch (c = *s) {
  112.         case 'n':  seq_buf[i++] = LF; break;
  113.         case 'r':  seq_buf[i++] = CR; break;
  114.         case 't':  seq_buf[i++] = '\t'; break;
  115.         case 'b':  seq_buf[i++] = '\b'; break;
  116.         case 'q':  seq_buf[i++] = '?';  break;
  117. #ifdef COMMENT
  118. /* The default case should catch these now... */
  119.         case '~':  seq_buf[i++] = '~';  break;
  120.         case '-':  seq_buf[i++] = '-';  break;
  121. #endif /* COMMENT */
  122.         case '\'': seq_buf[i++] = '\''; break;
  123.         case '\"': seq_buf[i++] = '\"'; break;
  124.         case 's':  seq_buf[i++] = ' ';  break;
  125.         case 'x':  seq_buf[i++] = '\021'; break;
  126.         case 'c':  no_cr = 1; break;
  127.         case 'd': {            /* send what we have & then */
  128.             seq_buf[i] = '\0';        /* expect to send rest after */
  129.             no_cr = 1;            /* sender delays a little */
  130.             s++;
  131.             return(1);
  132.         }
  133.         case 'w': {            /* wait count */
  134.             exp_alrm = 15;        /* default to 15 sec */
  135.             if (isdigit(*(s+1))) { 
  136.             s++;
  137.             exp_alrm = *s & 15;
  138.             if (isdigit(*(s+1)) ) {
  139.                 s++;
  140.                 exp_alrm = exp_alrm * 10 + (*s & 15);
  141.             }
  142.             }
  143.             break;
  144.         }
  145.         default:
  146.             if ( isdigit(c) ) {            /* octal character */
  147.                 oct_char = (c & 7);    /* most significant digit */
  148.             if (isdigit( *(s+1) ) ) {
  149.                 s++;
  150.                 oct_char = (oct_char<<3) | ( *s & 7 ) ;
  151.                 if (isdigit( *(s+1) ) ) {
  152.                 s++;
  153.                     oct_char = (oct_char<<3) | ( *s & 7 ) ;
  154.                 }
  155.             }
  156.             seq_buf[i++] = oct_char;
  157.             break;
  158.             } else seq_buf[i++] = *s; /* Treat ~ as quote */
  159.           }
  160.     } else seq_buf[i++] = *s;    /* Plain old character */
  161.     s++;
  162.     }
  163.     seq_buf[i] = '\0';
  164.     return(0);                /* end of space, return anyway */
  165. }
  166.  
  167. /*
  168.  Receive sequence -- see if expected response comes,
  169.  return success (or failure) in got_it.
  170. */ 
  171. static VOID
  172. recvseq()  {
  173.    
  174.     char *e, got[7], trace[SBUFL];
  175.     int i, l, x;
  176.     
  177.     sequenc();
  178.     l = (int)strlen(e=seq_buf);    /* no more than 7 chars allowed */
  179.     if (l > 7) {
  180.         e += l-7;
  181.         l = 7;
  182.     }
  183.     tlog(F111,"expecting sequence",e,(long) l);
  184.     if (l == 0) {        /* null sequence, just delay a little */
  185.         sleep (NULL_EXP);
  186.         got_it = 1;
  187.         tlog(F100,"got it (null sequence)","",0L);
  188.         return;
  189.     }
  190.     *trace = '\0';
  191.     for (i = 0; i < 7; i++) got[i]='\0';
  192.  
  193.     signal(SIGALRM,scrtime);    /* did we get it? */
  194.     if (!setjmp(alrmrng)) {        /* not timed out yet */
  195.         alarm(exp_alrm);
  196.         while (!got_it) {
  197.         for (i = 0; i < l-1; i++) got[i] = got[i+1]; /* Shift over */
  198.         x = ttinc(0);        /* Read a character */
  199.         debug(F101,"recvseq","",x);
  200.         if (x < 0) goto rcvx;    /* Check for error */
  201. #ifdef NETCONN
  202. #ifdef TNCODE
  203. /* Check for telnet protocol negotiation */
  204.         if (network &&
  205.             (ttnproto == NP_TELNET) &&
  206.             ( (x & 0xff) == IAC) ) {
  207.             switch (tn_doop((CHAR)(x & 0xff),duplex,ttinc)) {
  208.               case 2: duplex = 0; continue;
  209.               case 1: duplex = 1;
  210.               default: continue;
  211.             }
  212.         }
  213. #endif /* TNCODE */
  214. #endif /* NETCONN */
  215.         got[l-1] = x & 0x7f;    /* Got a character */
  216.         if (scr_echo) conoc(got[l-1]); /* Echo it */
  217.         if (seslog)        /* Log it in session log */
  218.           if (zchout(ZSFILE,got[l-1]) < 0) seslog = 0;
  219.         if ((int)strlen(trace) < sizeof(trace)-2 ) 
  220.           strcat(trace,dbchr(got[l-1]));
  221.         got_it = (!strncmp(e, got, l));
  222.         }
  223.     } else got_it = 0;        /* timed out here */
  224. rcvx:
  225.     alarm(0);
  226.     signal(SIGALRM,SIG_IGN);
  227.     tlog(F110,"received sequence: ",trace,0L);
  228.     tlog(F101,"returning with got-it code","",(long) got_it);
  229.     return;
  230. }
  231.  
  232. /*
  233.  Output A Sequence starting at pointer s,
  234.  return 0 if okay,
  235.  1 if failed to read (modem hangup or whatever)
  236. */
  237. static int oseqret = 0;            /* Return code for outseq */
  238.                     /* Out here to prevent clobbering */
  239.                     /* by longjmp. */
  240. static int
  241. outseq() {
  242.     char *sb;
  243.     int l;
  244.     int delay;
  245.  
  246.     oseqret = 0;            /* Initialize return code */
  247.     while(1) {
  248.     delay = sequenc();  
  249.     l = (int)strlen(seq_buf);
  250.     tlog(F111,"sending sequence ",seq_buf,(long) l);
  251.     signal(SIGALRM,scrtime);
  252.     if (!setjmp(alrmrng)) {
  253.         alarm(SND_ALRM);
  254.         if (!strcmp(seq_buf,"EOT")) {
  255.         ttoc(dopar('\004'));
  256.         if (scr_echo) conol("<EOT>");
  257.         if (seslog && duplex) if (zsout(ZSFILE,"<EOT>") < 0)
  258.           seslog = 0;
  259.         } else if (!strcmp(seq_buf,"BREAK") ||
  260.                !strcmp(seq_buf,"\\b") ||
  261.                !strcmp(seq_buf,"\\B")) {
  262.         ttsndb();
  263.         if (scr_echo) conol("<BREAK>");
  264.         if (seslog) if (zsout(ZSFILE,"{BREAK}") < 0) seslog = 0;
  265.         } else {
  266.         if (l > 0) {
  267.             for ( sb = seq_buf; *sb; sb++)
  268.               *sb = dopar(*sb);    /* add parity */
  269.             ttol((CHAR *)seq_buf,l); /* send it */
  270.             if (scr_echo && duplex) conxo(l,seq_buf);
  271.             if (seslog && duplex) /* log it */
  272.               if (zsout(ZSFILE,seq_buf) < 0)
  273.             seslog=0;
  274.         }
  275.         if (!no_cr) {
  276.             ttoc( dopar(CR) );
  277.             if (seslog && duplex)
  278.               if (zchout(ZSFILE,dopar(CR)) < 0)
  279.             seslog = 0;
  280.         }
  281.         }
  282.     } else oseqret |= -1;        /* else -- alarm rang */
  283.     alarm(0);
  284.     signal(SIGALRM,SIG_IGN);
  285.     if (!delay) return(oseqret);
  286. #ifndef MAC
  287.     msleep(DEL_MSEC);        /* delay, loop to next send */
  288. #endif /* MAC */
  289.     }
  290. }
  291.  
  292. /*  L O G I N  --  Login to remote system */
  293.  
  294. int
  295. dologin(cmdstr) char *cmdstr; {
  296.  
  297.     SIGTYP (*savealm)();        /* save incoming alarm function */
  298.     char *e;
  299.  
  300.     s = cmdstr;            /* make global to ckuscr.c */
  301.  
  302.     tlog(F100,loginv,"",0L);
  303.  
  304.     if (speed < 0L) speed = ttgspd();
  305.     if (ttopen(ttname,&local,mdmtyp,0) < 0) {
  306.         sprintf(seq_buf,"Sorry, can't open %s",ttname);
  307.         perror(seq_buf);
  308.         return(0);
  309.         }
  310.     /* Whether to echo script cmds */
  311.     scr_echo = (!quiet && !backgrd && secho);
  312. #ifndef NOSPL
  313.     if (scr_echo && cmdlvl > 1) {
  314.         if (cmdstk[cmdlvl].src == CMD_TF)
  315.           scr_echo = techo;
  316.         if (cmdstk[cmdlvl].src == CMD_MD)
  317.           scr_echo = mecho;
  318.     }
  319. #endif /* NOSPL */
  320.         if (scr_echo) {
  321. #ifdef NETCONN
  322.         if (network)
  323.           printf("Executing SCRIPT to host %s.\n",ttname);
  324.         else
  325. #endif /* NETCONN */
  326.           printf("Executing SCRIPT through %s, speed %ld.\n",ttname,speed);
  327.     }
  328.     *seq_buf=0;
  329.     for (e = s; *e; e++) strcat(seq_buf, dbchr(*e) );
  330. #ifdef COMMENT
  331. /* Skip this because it tends to contain a password... */
  332.     if (scr_echo) printf("SCRIPT string: %s\n",seq_buf);
  333. #endif /* COMMENT */
  334.     tlog(F110,"SCRIPT string: ",seq_buf, 0L);
  335.  
  336. /* Condition console terminal and communication line */        
  337.  
  338.     if (ttvt(speed,flow) < 0) {
  339.         printf("Sorry, Can't condition communication line\n");
  340.         return(0);
  341.         }
  342.     /* Save initial timer interrupt value */
  343.     savealm = signal(SIGALRM,SIG_IGN);
  344.  
  345. #ifdef NETCONN
  346. #ifdef TNCODE
  347.     /* No flushing on a TELNET connection */
  348.     if (!(network && (ttnproto == NP_TELNET)))
  349. #endif /* TNCODE */
  350. #endif /* NETCONN */
  351.       flushi();        /* flush stale input */
  352.  
  353. /* start expect - send sequence */
  354.  
  355.     while (*s) {        /* while not done with buffer */
  356.  
  357.     while (*s && isspace(*s)) s++;    /* skip over separating whitespaces */
  358.                     /* gather up expect sequence */
  359.     got_it = 0;
  360.     recvseq();
  361.  
  362.     while (!got_it) {        /* Have it yet? */
  363.         if (*s++ != '-')        /* No, is there a conditional send? */
  364.           goto failret;        /* No, return failure */
  365.         flushi();            /* Yes, flush out input buffer */
  366.         if (outseq())        /* If unable to send, */
  367.           goto failret;        /* return failure. */
  368.         if (*s++ != '-')        /* If no conditional response here, */
  369.           goto failret;        /* return failure. */
  370.         recvseq();            /* All OK, read response from host. */
  371.     }                /* Loop back and check got_it */
  372.  
  373.     while (*s && !isspace(*s++) ) ;    /* Skip over conditionals */
  374.     while (*s && isspace(*s)) s++;    /* Skip over separating whitespaces */
  375.     flushi();            /* Flush */
  376.     if (*s) if (outseq()) goto failret; /* If any */
  377.     }
  378.     signal(SIGALRM,savealm);
  379.     if (scr_echo) printf("Script successful.\n");
  380.     tlog(F100,"Script successful.","",0L);
  381.     return(1);
  382.  
  383. failret:
  384.     signal(SIGALRM,savealm);
  385.     if (scr_echo) printf("Sorry, script failed\n");
  386.     tlog(F100,"Script failed","",0L);
  387.     return(0);
  388. }
  389.  
  390. /*  F L U S H I  --  Flush, but log, input buffer  */
  391.  
  392. VOID
  393. flushi() {
  394.     int n;
  395.     if (seslog) {            /* Logging session? */
  396.         n = ttchk();            /* Yes, anything in buffer? */
  397.         if (n > 0) {            /* If so, */
  398.         if (n > SBUFL) n = SBUFL;    /* make sure not too much, */
  399.         n = ttxin(n,(CHAR *)fls_buf); /* then read it, */
  400.         if (n > 0) if (zsout(ZSFILE,fls_buf) < 0) seslog = 0;
  401.     }
  402.     } else ttflui();            /* Otherwise just flush. */
  403. }
  404.  
  405. #ifdef MAC
  406. alarm (s) int s; {            /* Fix this later */
  407. }
  408. #endif /* MAC */
  409. #else
  410. char *loginv = "Script Command Disabled";
  411. #endif /* NOSCRIPT */
  412. #endif /* NOICP */
  413.